package com.company.anr.service;

import com.company.anr.config.AnrConfig;
import com.company.anr.model.SN;
import com.company.anr.utils.FileUtils;
import com.company.anr.service.FileProcessingService;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.*;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogEntries;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class WebAutomationService {

    private static final Logger logger = LoggerFactory.getLogger(WebAutomationService.class);

    @Autowired
    private FileProcessingService fileProcessingService;

    @Autowired
    private AnrConfig anrConfig;

    @Value("${download.directory:${anr.work.directory}}")
    private String downloadDirectory;

    @Value("${anr.runMonkey:false}")
    private boolean runMonkey;

    @Value("${anr.monkey.deadline.hour:11}")
    private int monkeyDeadlineHour;

    // 配置信息
    private static final String LOGIN_URL = "https://iot-admin.zuoyebang.cc/iot-admin-server/index";
    private static final String ERROR_LOG_URL = "https://iot-admin.zuoyebang.cc/iot-admin-server/system/errorlog/table";
    private static final int DEFAULT_TIMEOUT = 10;
    private static final int DOWNLOAD_TIMEOUT = 300; // 5分钟

    private WebDriver driver;
    private WebDriverWait wait;

    /**
     * 初始化浏览器 - 强制使用远程调试方案（连接手动启动的Chrome）
     */
    public void initializeBrowser() {
        logger.info("开始初始化浏览器 - 强制使用远程调试方案...");
        try {
            initializeBrowserWithRemoteDebug();
        } catch (Exception e) {
            logger.error("远程调试方案失败: {}", e.getMessage());
            logger.error("错误详情: ", e);
            throw new RuntimeException("无法连接到Chrome调试实例，请确保Chrome以调试模式启动: " + e.getMessage(), e);
        }
    }

    /**
     * 方案1：远程调试端口方案（优先使用）
     */
    private void initializeBrowserWithRemoteDebug() throws MalformedURLException {
        logger.info("开始初始化浏览器 - 使用远程调试端口方案...");

        // 首先检查Chrome调试端口是否可用
        if (!isChromeDebugPortAvailable()) {
            throw new RuntimeException("Chrome调试端口9222不可用，请先运行start-chrome-debug.bat启动Chrome调试模式");
        }

        logger.info("Chrome调试端口9222可用，开始连接...");

        // 设置ChromeDriver路径
        System.setProperty("webdriver.chrome.driver", "C:\\Windows\\chromedriver.exe");

        ChromeOptions options = new ChromeOptions();

        // 关键：连接到手动启动的Chrome调试实例
        options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
        logger.info("设置debuggerAddress: 127.0.0.1:9222");

        // 避免被检测为自动化
        options.addArguments("--disable-blink-features=AutomationControlled");
        options.addArguments("--disable-extensions");
        options.addArguments("--no-sandbox");
        options.addArguments("--disable-dev-shm-usage");

        logger.info("使用ChromeDriver连接到调试实例...");
        try {
            // 使用ChromeDriver连接到调试实例
            driver = new ChromeDriver(options);
            logger.info("成功连接到Chrome调试实例！");
        } catch (Exception e) {
            logger.error("连接Chrome调试实例失败: {}", e.getMessage());
            logger.error("错误详情: ", e);
            throw new RuntimeException("无法连接到Chrome调试实例: " + e.getMessage(), e);
        }

        logger.info("设置窗口大小...");
        driver.manage().window().maximize();

        logger.info("创建WebDriverWait...");
        wait = new WebDriverWait(driver, Duration.ofSeconds(DEFAULT_TIMEOUT));

        logger.info("浏览器初始化成功 - 已接管现有Chrome窗口");

        // 自动访问IoT平台
        logger.info("自动访问IoT平台...");
        driver.get(LOGIN_URL);
        try {
            Thread.sleep(3000); // 等待页面加载
        } catch (InterruptedException e) {
            logger.warn("等待页面加载时被中断: {}", e.getMessage());
            Thread.currentThread().interrupt();
        }
        logger.info("IoT平台页面已打开，等待用户登录");
    }

    /**
     * 检查Chrome调试端口是否可用
     */
    private boolean isChromeDebugPortAvailable() {
        try {
            java.net.Socket socket = new java.net.Socket("localhost", 9222);
            socket.close();
            logger.info("Chrome调试端口9222可用");
            return true;
        } catch (Exception e) {
            logger.warn("Chrome调试端口9222不可用: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 初始化浏览器 - 方案1：复用用户配置文件方案（备选）
     */
    private void initializeBrowserWithLocalProfile() {
        try {
            logger.info("开始初始化浏览器 - 使用本地配置文件方案...");

            // 设置ChromeDriver路径
            System.setProperty("webdriver.chrome.driver", "C:\\Windows\\chromedriver.exe");

            ChromeOptions options = new ChromeOptions();

            // 使用本地Chrome配置文件（请替换<你的用户名>为实际用户名）
            options.addArguments("user-data-dir=C:\\Users\\FX\\AppData\\Local\\Google\\Chrome\\User Data");
            options.addArguments("profile-directory=Default");

            // 避免被检测为自动化
            options.addArguments("--disable-blink-features=AutomationControlled");
            options.setExperimentalOption("excludeSwitches", new String[] { "enable-automation" });
            options.setExperimentalOption("useAutomationExtension", false);

            // 下载配置
            Map<String, Object> prefs = new HashMap<>();
            prefs.put("download.default_directory", downloadDirectory);
            prefs.put("download.prompt_for_download", false);
            prefs.put("download.directory_upgrade", true);
            prefs.put("safebrowsing.enabled", false); // 若失败，试改回true
            options.setExperimentalOption("prefs", prefs);

            // 可选日志捕获
            options.setCapability("goog:loggingPrefs", Map.of("browser", "ALL"));

            logger.info("创建ChromeDriver实例...");
            driver = new ChromeDriver(options);

            logger.info("设置窗口大小...");
            driver.manage().window().maximize();

            logger.info("创建WebDriverWait...");
            wait = new WebDriverWait(driver, Duration.ofSeconds(DEFAULT_TIMEOUT));

            logger.info("浏览器初始化成功 - 使用本地配置文件");
        } catch (Exception e) {
            logger.error("本地配置文件方案也失败: {}", e.getMessage(), e);
            throw new RuntimeException("所有浏览器初始化方案都失败: " + e.getMessage(), e);
        }
    }

    /**
     * 登录网站
     *
     * @param username 用户名
     * @param password 密码
     */
    public void login(String username, String password) {
        try {
            logger.info("开始登录，访问URL: {}", LOGIN_URL);
            driver.get(LOGIN_URL);

            // 等待页面完全加载 - 增加等待时间
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                logger.warn("等待页面加载时被中断: {}", e.getMessage());
                Thread.currentThread().interrupt();
            }

            logger.info("等待页面元素加载...");
            // 等待页面加载 - 使用更长的超时时间
            WebDriverWait longWait = new WebDriverWait(driver, Duration.ofSeconds(30));
            longWait.until(ExpectedConditions.presenceOfElementLocated(By.className("el-input__inner")));

            logger.info("找到输入框，开始输入用户名和密码");
            // 输入用户名和密码，前端那边就默认写成自己的
            driver.findElement(By.xpath("//input[@placeholder='请输入邮箱前缀']")).sendKeys(username);
            driver.findElement(By.xpath("//input[@placeholder='请输入密码']")).sendKeys(password);

            // 点击登录按钮
            logger.info("点击登录按钮");
            driver.findElement(By.cssSelector("button[type='button']")).click();

            try {
                Thread.sleep(3000); // 等待登录完成
            } catch (InterruptedException e) {
                logger.warn("等待登录完成时被中断: {}", e.getMessage());
                Thread.currentThread().interrupt();
            }
            logger.info("登录成功");

        } catch (Exception e) {
            logger.error("登录失败: {}", e.getMessage());
            // 保存页面截图用于调试
            try {
            String screenshotPath = java.nio.file.Paths.get(anrConfig.getWorkDirectory())
                    .resolve("login_error_" + System.currentTimeMillis() + ".png").toString();
            ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE).renameTo(new java.io.File(screenshotPath));
                logger.info("登录失败截图已保存: {}", screenshotPath);
            } catch (Exception screenshotException) {
                logger.error("保存截图失败: {}", screenshotException.getMessage());
            }
            throw new RuntimeException("登录失败", e);
        }
    }

    // /**
    // * 下载设备日志 - 完全按照Python脚本的逻辑实现
    // *
    // * @param deviceSn 设备SN
    // * @param phone 手机号
    // * @return 下载的文件名
    // */
    // public String downloadDeviceLogs(String deviceSn, String phone) {
    //
    // }

    private static String readFileContent(String filePath) throws IOException {
        // 使用UTF-8编码读取文件
        return new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
    }

    /**
     * 检查设备状态并发送通知
     *
     * @return 设备是否在线
     */
    private boolean checkDeviceStatusAndNotify() {
        try {
            int clickCount = 1;
            while (true) {
                // 点击发送日志上传通知按钮 - 使用Python脚本相同的XPath
                wait.until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body/div[2]/div/button"))).click();

                // 处理通知提示框 - 使用Python脚本相同的逻辑
                WebElement messageElement = wait.until(ExpectedConditions
                        .presenceOfElementLocated(By.xpath("//*[@id=\"layui-layer" + clickCount + "\"]/div[2]")));
                String message = messageElement.getText();
                logger.info("设备状态消息: {}", message);

                // 确认消息
                wait.until(ExpectedConditions
                        .elementToBeClickable(By.xpath("//*[@id=\"layui-layer" + clickCount + "\"]/div[3]/a"))).click();

                clickCount++;

                if (message.contains("设备不在线")) {
                    logger.warn("设备不在线，请确认设备在线后重试");
                    // 根据Python脚本逻辑，设备不在线时应该等待用户确认
                    // 这里可以选择抛出异常或者返回false，让调用者决定如何处理
                    return false;
                } else {
                    logger.info("设备状态检查通过，通知发送成功");
                    return true;
                }
            }
        } catch (Exception e) {
            logger.error("检查设备状态失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 关闭浏览器
     */
    public void closeBrowser() {
        if (driver != null) {
            try {
                // 输出浏览器日志用于调试下载问题
                try {
                    LogEntries logEntries = driver.manage().logs().get("browser");
                    logger.info("浏览器日志条目数: {}", logEntries.getAll().size());
                    for (LogEntry entry : logEntries.getAll()) {
                        // 输出所有日志用于调试
                        System.out.println("浏览器日志: " + entry.getMessage());
                        // 特别关注下载相关日志
                        if (entry.getMessage().contains("download") || entry.getMessage().contains("error")
                                || entry.getMessage().contains("blocked")) {
                            logger.warn("重要浏览器日志: {}", entry.getMessage());
                        }
                    }
                } catch (Exception logException) {
                    logger.warn("获取浏览器日志失败: {}", logException.getMessage());
                }

                driver.quit();
                logger.info("浏览器已关闭");
            } catch (Exception e) {
                logger.error("关闭浏览器时出错: {}", e.getMessage());
            }
        }
    }

    /**
     * 检查浏览器是否已初始化
     *
     * @return 是否已初始化
     */
    public boolean isInitialized() {
        return driver != null;
    }

    /**
     * 使用Python脚本相同的下载逻辑
     * 这个方法完全复制Python脚本的下载机制
     */
    public String downloadDeviceLogsPythonStyle(String deviceSn, String phone) {
        try {
            // 打开错误日志页面
            driver.get(ERROR_LOG_URL);

            // 定位输入框 - 使用Python脚本相同的选择器
            WebElement firstSnInput = driver
                    .findElement(By.xpath("//*[@id=\"form-key-get\"]/div/div/div/div[1]/input"));
            WebElement secondSnInput = driver.findElement(By.xpath("//*[@id=\"form-search\"]/div/ul/li[1]/input"));
            WebElement phoneInput = driver.findElement(By.xpath("//*[@id=\"form-key-get\"]/div/div/div/div[3]/input"));

            // 填写信息
            firstSnInput.sendKeys(deviceSn);
            phoneInput.sendKeys(phone);

            // 检查设备状态
            if (!checkDeviceStatusAndNotify()) {
                throw new RuntimeException("设备不在线或状态检查失败");
            }

            // 填写第二个SN输入框
            secondSnInput.sendKeys(deviceSn);

            // 点击搜索按钮 - 使用Python脚本相同的选择器
            wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"form-search\"]/div/ul/li[2]/a[1]")))
                    .click();

            // 等待下载链接出现并下载 - 使用Python脚本相同的逻辑
            return waitAndDownloadPythonStyle();

        } catch (Exception e) {
            logger.error("下载设备日志失败: {}", e.getMessage());
            throw new RuntimeException("下载设备日志失败", e);
        }
    }

    /**
     *
     */
    private String waitAndDownloadPythonStyle() {
        try {
            logger.info("开始等待下载链接出现...");

            // 等待页面完全加载
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                logger.warn("等待页面加载时被中断: {}", e.getMessage());
                Thread.currentThread().interrupt();
            }

            // 使用Python脚本完全相同的选择器和逻辑
            List<WebElement> downloadLinks = wait.until(driver -> {
                List<WebElement> elements = driver
                        .findElements(By.xpath("//*[@id=\"bootstrap-table\"]/tbody/tr/td[6]/a"));
                return elements.isEmpty() ? null : elements;
            });

            if (downloadLinks == null || downloadLinks.isEmpty()) {
                return null;
            }

            // 选择第一个（最新的）下载链接
            int index = 0; // 选择第一个（最新的）
            WebElement downloadLink = downloadLinks.get(index);
            logger.info("找到 {} 个下载链接，选择第{}个（第一个/最新的）", downloadLinks.size(), index + 1);

            // 获取期望的文件名（完全按照Python脚本）
            String href = downloadLink.getAttribute("href");
            logger.info("下载链接href: {}", href);

            String expectedFilename = FileUtils.extractFilenameFromUrl(href);
            logger.info("期望的文件名: {}", expectedFilename);

            // 直接点击下载（完全按照Python脚本）
            downloadLink.click();
            logger.info("成功点击下载按钮");

            // 等待文件下载完成
            Path downloadDir = Paths.get(downloadDirectory);

            // 等待文件下载完成（完全按照Python脚本的等待逻辑）
            Path downloadedFile = FileUtils.waitForFile(downloadDir, expectedFilename, 1600);

            if (downloadedFile != null) {
                logger.info("文件下载完成: {}", downloadedFile);
                return downloadedFile.getFileName().toString();
            } else {
                return null;
            }

        } catch (Exception e) {
            logger.error("等待下载失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 调试方法：分析页面中的下载按钮
     * 这个方法可以帮助您了解页面结构，用于调试下载问题
     */
    public void debugDownloadButtons() {
        try {
            logger.info("开始调试页面中的下载按钮...");

            // 等待页面加载
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                logger.warn("等待页面加载时被中断: {}", e.getMessage());
                Thread.currentThread().interrupt();
            }

            // 1. 查找所有包含"下载"文本的元素
            List<WebElement> allDownloadElements = driver.findElements(By.xpath("//*[contains(text(), '下载')]"));
            logger.info("找到 {} 个包含'下载'文本的元素", allDownloadElements.size());

            for (int i = 0; i < allDownloadElements.size(); i++) {
                WebElement element = allDownloadElements.get(i);
                logger.info("元素 {}: 标签={}, 文本={}, 类名={}", i + 1, element.getTagName(), element.getText().trim(),
                        element.getAttribute("class"));
            }

            // 2. 查找所有按钮样式的链接
            List<WebElement> buttonLinks = driver.findElements(By.cssSelector("a.btn"));
            logger.info("找到 {} 个按钮样式的链接", buttonLinks.size());

            for (int i = 0; i < buttonLinks.size(); i++) {
                WebElement element = buttonLinks.get(i);
                logger.info("按钮链接 {}: 文本={}, 类名={}, href={}", i + 1, element.getText().trim(),
                        element.getAttribute("class"), element.getAttribute("href"));
            }

            // 3. 查找表格中的下载链接
            List<WebElement> tableLinks = driver.findElements(By.cssSelector("table a"));
            logger.info("找到 {} 个表格中的链接", tableLinks.size());

            for (int i = 0; i < tableLinks.size(); i++) {
                WebElement element = tableLinks.get(i);
                if (element.getText().contains("下载")) {
                    logger.info("表格下载链接 {}: 文本={}, 类名={}, href={}", i + 1, element.getText().trim(),
                            element.getAttribute("class"), element.getAttribute("href"));
                }
            }

            // 4. 保存页面截图
            String screenshotPath = java.nio.file.Paths.get(anrConfig.getWorkDirectory())
                    .resolve("debug_page_" + System.currentTimeMillis() + ".png").toString();
            ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE).renameTo(new File(screenshotPath));
            logger.info("调试截图已保存: {}", screenshotPath);

            // 5. 获取页面HTML源码（部分）
            String pageSource = driver.getPageSource();
            if (pageSource.length() > 10000) {
                pageSource = pageSource.substring(0, 10000) + "...";
            }
            logger.info("页面源码片段: {}", pageSource);

        } catch (Exception e) {
            logger.error("调试下载按钮时出错: {}", e.getMessage(), e);
        }
    }

    /**
     * 完整的自动化流程 - 模拟Python脚本的完整功能
     * 这个方法实现了图片中显示的5个步骤，并在下载完成后自动处理文件
     *
     * @param username 用户名
     * @param password 密码
     * @param deviceSn 设备SN
     * @param phone    手机号
     * @return 下载的文件名
     */
    public String executeFullAutomationWorkflow(String username, String password, String deviceSn, String phone) {
        try {
            logger.info("开始执行完整的自动化工作流程");
            logger.info("参数 - 用户名: {}, 设备SN: {}, 手机号: {}", username, deviceSn, phone);

            // 确保浏览器已初始化
            if (!isInitialized()) {
                logger.info("浏览器未初始化，开始初始化...");
                initializeBrowser();
            }

            // 跳过登录步骤，因为用户已经手动登录了
            logger.info("跳过登录步骤，用户已手动登录");

            // 直接执行5步流程
            logger.info("开始执行5步自动化流程");

            try {
                logger.info("开始执行设备日志下载流程 - SN: {}, Phone: {}", deviceSn, phone);

                // 步骤1: 直接跳转到日志页面（完全按照Python脚本）
                logger.info("步骤1: 直接跳转到日志管理页面");
                driver.get(ERROR_LOG_URL);

                // 等待页面加载
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }

                // 步骤2: 定位输入框（完全按照Python脚本的XPath）
                logger.info("步骤2: 定位输入框");
                WebElement firstSnInput = driver
                        .findElement(By.xpath("//*[@id=\"form-key-get\"]/div/div/div/div[1]/input"));
                WebElement secondSnInput = driver.findElement(By.xpath("//*[@id=\"form-search\"]/div/ul/li[1]/input"));
                WebElement phoneInput = driver
                        .findElement(By.xpath("//*[@id=\"form-key-get\"]/div/div/div/div[3]/input"));

                // // 步骤3: 填写手机号和SN（完全按照Python脚本）
                // logger.info("步骤3: 填写手机号和SN");
                // phoneInput.sendKeys(phone);
                // firstSnInput.sendKeys(deviceSn);
                //
                // // 步骤4: 点击通知按钮并处理设备状态（完全按照Python脚本）
                // logger.info("步骤4: 点击通知按钮并检查设备状态");
                // if (!checkDeviceStatusAndNotify()) {
                // throw new RuntimeException("设备不在线或状态检查失败");
                // }
                String filePath = "D:\\ANR-WRITE\\ANRS.TXT";
                String result = "";
                String[] sns = null;
                String downloadedFile = null;
                try {
                    // 读取文件内容
                    String content = readFileContent(filePath);

                    // 将换行符替换为逗号
                    result = content.replaceAll("\\r?\\n", ",");
                    sns = result.split(",");
                } catch (IOException e) {
                    System.err.println("读取文件时发生错误: " + e.getMessage());
                    e.printStackTrace();
                }
                // 步骤5: 等待配置的时间（从配置文件读取）
                LinkedList<SN> snList = new LinkedList<>();
                if (sns != null) {
                    for (String sn : sns) {
                        SN sn1 = new SN();
                        sn1.setSn(sn);
                        sn1.setErrTime(0);
                        snList.add(sn1);
                    }
                }
                // 检查snList是否为空
                if (snList.isEmpty()) {
                    logger.warn("没有找到任何SN，使用默认的deviceSn: {}", deviceSn);
                    // 如果没有从文件读取到SN，使用传入的deviceSn
                    SN defaultSn = new SN();
                    defaultSn.setSn(deviceSn);
                    defaultSn.setErrTime(0);
                    snList.add(defaultSn);
                }

                while (!snList.isEmpty() && snList.size() > 0) {
                    int waitSeconds = anrConfig.getAutomationNotificationWaitSeconds();
                    logger.info("步骤5: 等待{}秒（从配置文件读取）", waitSeconds);
                    try {
                        Thread.sleep(waitSeconds * 1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("等待过程被中断");
                    }

                    // 步骤6: 填写第二个SN输入框并搜索
                    logger.info("步骤6: 填写第二个SN输入框并搜索");
                    SN sn = snList.poll();
                    deviceSn = sn.getSn();
                    Integer errTime = sn.getErrTime();

                    // 清空搜索框，避免SN累积
                    secondSnInput.clear();
                    secondSnInput.sendKeys(deviceSn);

                    // 点击搜索按钮
                    wait.until(ExpectedConditions
                            .elementToBeClickable(By.xpath("//*[@id=\"form-search\"]/div/ul/li[2]/a[1]"))).click();

                    String time = fetchFirstRowUploadTimeSafe();
                    if (runMonkey) {
                        if (time == null || time.isEmpty()) {
                            logger.info("runMonkey=true，但未获取到上传时间，跳过 SN: {}", deviceSn);
                            continue;
                        }
                        try {
                            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                            LocalDateTime ts = LocalDateTime.parse(time, dtf);
                            LocalTime deadline = LocalTime.of(monkeyDeadlineHour, 0);
                            if (!ts.toLocalTime().isBefore(deadline)) {
                                logger.info("runMonkey=true，上传时间 {} 不早于 {}:00，跳过 SN: {}", time, monkeyDeadlineHour, deviceSn);
                                continue;
                            } else {
                                logger.info("runMonkey=true，上传时间 {} 早于 {}:00，继续处理 SN: {}", time, monkeyDeadlineHour, deviceSn);
                            }
                        } catch (Exception pe) {
                            logger.warn("runMonkey=true，解析上传时间失败: {}，跳过 SN: {}", pe.getMessage(), deviceSn);
                            continue;
                        }
                    }

                    // 步骤7: 下载文件
                    logger.info("步骤7: 下载文件");
                    downloadedFile = waitAndDownloadPythonStyle();
                    // 确保有返回值
                    if (downloadedFile == null && errTime <= 6) {
                        sn.setErrTime(++errTime);
                        snList.offer(sn);
                    } else {
                        logger.info("自动化工作流程执行完成，下载文件: {}", downloadedFile);
                        // 下载完成后，自动触发文件处理流程
                        if (downloadedFile != null && !downloadedFile.isEmpty()) {
                            logger.info("开始自动处理下载的文件: {}", downloadedFile);
                            processDownloadedFile(downloadedFile, deviceSn);
                        }

                    }
                    if (errTime > 6) {
                        // todo 建一个数据库，把这个sn记录到errsn表
                    }
                }
            } catch (Exception e) {
                logger.error("下载设备日志失败: {}", e.getMessage());
                throw new RuntimeException("下载设备日志失败", e);
            }

        } catch (Exception e) {
            logger.error("自动化工作流程执行失败: {}", e.getMessage());
            throw new RuntimeException("自动化工作流程执行失败", e);
        }

        return null; // 如果所有SN都处理失败，返回null
    }
    /**
     * 提取第一行的“上传时间”。优先通过表头文本定位列索引，找不到则按时间格式回退匹配。
     */
    public String fetchFirstRowUploadTime() {
        // 1) 根据表头定位“上传时间”的列索引（1-based）
        Integer colIndex = findUploadTimeColumnIndex();

        if (colIndex != null) {
            WebElement cell = driver.findElement(By.xpath("//*[@id='bootstrap-table']/tbody/tr[1]/td[" + colIndex + "]"));
            String text = cell.getText().trim();
            if (!text.isEmpty()) {
                return text;
            }
        }

        // 2) 回退：扫描第一行所有单元格，找符合 yyyy-MM-dd HH:mm:ss 的文本
        List<WebElement> cells = driver.findElements(By.xpath("//*[@id='bootstrap-table']/tbody/tr[1]/td"));
        Pattern p = Pattern.compile("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}");
        for (WebElement c : cells) {
            String t = c.getText();
            if (t != null) {
                Matcher m = p.matcher(t);
                if (m.find()) {
                    return m.group();
                }
            }
        }
        return null;
    }
    private Integer findUploadTimeColumnIndex() {
        try {
            List<WebElement> headers = driver.findElements(By.xpath("//*[@id='bootstrap-table']/thead//th"));
            int idx = 0;
            for (int i = 0; i < headers.size(); i++) {
                String txt = headers.get(i).getText();
                // 有些表头可能带空格/换行，统一去空白比较
                if (txt != null && txt.replace(" ", "").contains("上传时间")) {
                    idx = i + 1; // XPath 1-based
                    break;
                }
            }
            return idx == 0 ? null : idx;
        } catch (NoSuchElementException e) {
            return null;
        }
    }

    /**
     * 简化的自动化流程 - 适用于已经登录的情况
     *
     * @param deviceSn 设备SN
     * @param phone    手机号
     * @return 下载的文件名
     */
    public String executeDeviceLogDownload(String deviceSn, String phone) {
        String downloadedFile = null; // 在方法开始就声明变量
        try {
            logger.info("开始执行设备日志下载流程 - SN: {}, Phone: {}", deviceSn, phone);

            // 确保浏览器已初始化
            if (!isInitialized()) {
                throw new RuntimeException("浏览器未初始化，请先调用initializeBrowser()");
            }

            logger.info("开始执行设备日志下载流程 - SN: {}, Phone: {}", deviceSn, phone);

            // 步骤1: 直接跳转到日志页面（完全按照Python脚本）
            logger.info("步骤1: 直接跳转到日志管理页面");
            driver.get(ERROR_LOG_URL);

            // 等待页面加载
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

            // 步骤2: 定位输入框（完全按照Python脚本的XPath）
            logger.info("步骤2: 定位输入框");
            WebElement firstSnInput = driver
                    .findElement(By.xpath("//*[@id=\"form-key-get\"]/div/div/div/div[1]/input"));
            WebElement secondSnInput = driver.findElement(By.xpath("//*[@id=\"form-search\"]/div/ul/li[1]/input"));
            WebElement phoneInput = driver.findElement(By.xpath("//*[@id=\"form-key-get\"]/div/div/div/div[3]/input"));

            // // 步骤3: 填写手机号和SN（完全按照Python脚本）
            // logger.info("步骤3: 填写手机号和SN");
            // phoneInput.sendKeys(phone);
            // firstSnInput.sendKeys(deviceSn);
            //
            // // 步骤4: 点击通知按钮并处理设备状态（完全按照Python脚本）
            // logger.info("步骤4: 点击通知按钮并检查设备状态");
            // if (!checkDeviceStatusAndNotify()) {
            // throw new RuntimeException("设备不在线或状态检查失败");
            // }
            String filePath = "D:\\ANR-WRITE\\ANRS.TXT";
            String result = "";
            String[] sns = null;
            try {
                // 读取文件内容
                String content = readFileContent(filePath);

                // 将换行符替换为逗号
                result = content.replaceAll("\\r?\\n", ",");
                sns = result.split(",");
            } catch (IOException e) {
                System.err.println("读取文件时发生错误: " + e.getMessage());
                e.printStackTrace();
            }
            // 步骤5: 等待配置的时间（从配置文件读取）
            LinkedList<SN> snList = new LinkedList<>();
            if (sns != null) {
                for (String sn : sns) {
                    SN sn1 = new SN();
                    sn1.setSn(sn);
                    sn1.setErrTime(0);
                    snList.add(sn1);
                }
            }
            // 检查snList是否为空
            if (snList.isEmpty()) {
                logger.warn("没有找到任何SN，使用默认的deviceSn: {}", deviceSn);
                // 如果没有从文件读取到SN，使用传入的deviceSn
                SN defaultSn = new SN();
                defaultSn.setSn(deviceSn);
                defaultSn.setErrTime(0);
                snList.add(defaultSn);
            }

            while (!snList.isEmpty() && snList.size() > 0) {
                int waitSeconds = anrConfig.getAutomationNotificationWaitSeconds();
                logger.info("步骤5: 等待{}秒（从配置文件读取）", waitSeconds);
                try {
                    Thread.sleep(waitSeconds * 1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("等待过程被中断");
                }

                // 步骤6: 填写第二个SN输入框并搜索
                logger.info("步骤6: 填写第二个SN输入框并搜索");
                SN sn = snList.poll();
                deviceSn = sn.getSn();
                Integer errTime = sn.getErrTime();

                // 清空搜索框，避免SN累积
                secondSnInput.clear();
                secondSnInput.sendKeys(deviceSn);

                // 点击搜索按钮
                wait.until(
                        ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"form-search\"]/div/ul/li[2]/a[1]")))
                        .click();

                // 步骤7: 下载文件
                logger.info("步骤7: 下载文件");
                downloadedFile = waitAndDownloadPythonStyle();
                // 确保有返回值
                if (downloadedFile == null && errTime <= 6) {
                    sn.setErrTime(++errTime);
                    snList.offer(sn);
                } else {
                    logger.info("自动化工作流程执行完成，下载文件: {}", downloadedFile);
                    // 下载完成后，自动触发文件处理流程
                    if (downloadedFile != null && !downloadedFile.isEmpty()) {
                        logger.info("开始自动处理下载的文件: {}", downloadedFile);
                        processDownloadedFile(downloadedFile, deviceSn);
                    }

                }
                if (errTime > 6) {
                    // todo 建一个数据库，把这个sn记录到errsn表
                }
            }
        } catch (Exception e) {
            logger.error("下载设备日志失败: {}", e.getMessage());
            throw new RuntimeException("下载设备日志失败", e);
        }

        return downloadedFile; // 返回下载的文件名
    }

    // Safer time extraction: waits table readiness and avoids NoSuchElement
    private String fetchFirstRowUploadTimeSafe() {
        try {
            // wait until table has at least one row (data or placeholder)
            try {
                new WebDriverWait(driver, Duration.ofSeconds(15)).until(d -> {
                    List<WebElement> rows = d.findElements(By.cssSelector("#bootstrap-table tbody tr"));
                    return rows.isEmpty() ? null : Boolean.TRUE;
                });
                try { Thread.sleep(300); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
            } catch (Exception ignore) {
                // continue; we'll probe DOM safely
            }

            List<WebElement> rows = driver.findElements(By.cssSelector("#bootstrap-table tbody tr"));
            if (rows.isEmpty()) return null;
            WebElement first = rows.get(0);
            String cls = first.getAttribute("class");
            if (cls != null && cls.contains("no-records-found")) return null;

            Integer colIndex = findUploadTimeColumnIndex();
            if (colIndex != null && colIndex > 0) {
                List<WebElement> tds = first.findElements(By.tagName("td"));
                if (colIndex <= tds.size()) {
                    String text = String.valueOf(tds.get(colIndex - 1).getText()).trim();
                    if (!text.isEmpty()) return text;
                }
            }

            // fallback: regex across all cells
            Pattern p = Pattern.compile("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}");
            for (WebElement td : first.findElements(By.tagName("td"))) {
                String t = td.getText();
                if (t != null) {
                    Matcher m = p.matcher(t);
                    if (m.find()) return m.group();
                }
            }
            return null;
        } catch (Exception e) {
            logger.warn("fetchFirstRowUploadTimeSafe failed: {}", e.getMessage());
            return null;
        }
    }

    private void processDownloadedFile(String downloadedFile, String deviceSn) {
        try {
            logger.info("开始处理下载的文件: {} for SN: {}", downloadedFile, deviceSn);

            // 等待文件完全下载
            Path downloadDir = Paths.get(downloadDirectory);
            Path zipFile = downloadDir.resolve(downloadedFile);

            // 等待文件存在
            int maxWaitTime = 30; // 最多等待30秒
            int waitTime = 0;
            while (!Files.exists(zipFile) && waitTime < maxWaitTime) {
                try {
                    Thread.sleep(1000);
                    waitTime++;
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("等待文件下载时被中断", e);
                }
            }

            if (!Files.exists(zipFile)) {
                logger.error("下载的文件不存在: {}", zipFile);
                return;
            }

            logger.info("文件下载完成，开始解压和处理: {}", zipFile);

            // 创建输出目录
            Path outputDir = Paths.get(anrConfig.getWorkPathForSn(deviceSn));
            Path detailDir = Paths.get(anrConfig.getDetailDirectory());

            // 创建DETAIL目录（如果不存在）
            Files.createDirectories(detailDir);

            // 使用FileProcessingService处理文件
            boolean success = fileProcessingService.extractAndCopy(zipFile, downloadDir, outputDir);

            if (success) {
                // 生成分析报告到DETAIL目录
                Path anrFolder = outputDir.resolve("anr");
                Path detailReportFile = Paths.get(anrConfig.getDetailReportPathForSn(deviceSn));

                if (Files.exists(anrFolder)) {
                    fileProcessingService.processAnrFolder(anrFolder, detailReportFile);
                    logger.info("分析报告已生成: {}", detailReportFile);
                } else {
                    // 即使没有anr文件夹，也要生成analysis.txt文件
                    logger.info("anr文件夹不存在，生成无ANR日志报告");
                    fileProcessingService.generateNoAnrReport(detailReportFile);
                    logger.info("无ANR日志报告已生成: {}", detailReportFile);
                }

                // 创建以SN命名的文件夹并复制文件
                // 使用getProcessedPathForSn获取按日期分类的路径
                Path snFolder = Paths.get(anrConfig.getProcessedPathForSn(deviceSn));
                Files.createDirectories(snFolder.getParent()); // 确保MM-dd目录存在
                fileProcessingService.createSnFolderAndCopyFiles(outputDir, snFolder);
                logger.info("已创建SN文件夹: {}", snFolder);

                logger.info("文件处理完成，输出目录: {}", outputDir);
                logger.info("SN文件夹: {}", snFolder);
                logger.info("详细分析报告: {}", detailReportFile);
            } else {
                logger.error("文件处理失败");
            }

        } catch (Exception e) {
            logger.error("处理下载文件时出错: {}", e.getMessage(), e);
        }
    }

}
